#include "screenshot.h"
#include "common.hpp"
#include <QLabel>
#include <QSpinBox>
#include <QCheckBox>
#include <QPushButton>
#include <QTimer>
#include <QStandardPaths>
#include <QDir>
#include <QFileDialog>
#include <QImageWriter>
#include <QMessageBox>
#include <QGuiApplication>
#include <QWindow>
#include <QApplication>
#include <QScreen>
#include <QGridLayout>
#include <QRect>
#include <QGroupBox>
#include <QDesktopWidget>


ScreenShot::ScreenShot(QWidget *parent) : QWidget(parent),
	m_pScreenshotLabel(nullptr),
	m_pDelaySpinBox(nullptr),
	m_pHideThisWindowCheckBox(nullptr),
	m_pNewScreenShotButton(nullptr)
{
	init();
	shootScreen();
	m_pDelaySpinBox->setValue(5);

	setWindowTitle(tr("ScreenShot"));
	resize(300 , 200);
}

ScreenShot::~ScreenShot()
{
	uninit();
}

void ScreenShot::resizeEvent(QResizeEvent *event)
{
	QSize scaledSize = m_originalPixmap.size();
	scaledSize.scale(m_pScreenshotLabel->size() , Qt::KeepAspectRatio);
	if(!m_pScreenshotLabel->pixmap() || scaledSize!=m_pScreenshotLabel->pixmap()->size())
	{
		updateScreenshotLabel();
	}
}

void ScreenShot::newScreenshot()
{
	if(m_pHideThisWindowCheckBox->isChecked())
	{
		hide();
	}
	m_pNewScreenShotButton->setDisabled(true);

	QTimer::singleShot(m_pDelaySpinBox->value() * 1000 ,  this , &ScreenShot::shootScreen);
}

void ScreenShot::saveScreenshot()
{
	const QString format = "png";
	QString initialPath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
	if(initialPath.isEmpty())
	{
		initialPath = QDir::currentPath();
	}
	initialPath += tr("/untitled.") + format;

	QFileDialog  fileDialog(this  , tr("Save As") , initialPath);
	fileDialog.setAcceptMode(QFileDialog::AcceptSave);
	fileDialog.setFileMode(QFileDialog::AnyFile);
	fileDialog.setDirectory(initialPath);

	QStringList  mimeTypes;
	foreach(const   QByteArray &bf ,  QImageWriter::supportedMimeTypes())
	{
		mimeTypes.append(QLatin1String(bf));
	}
	fileDialog.setMimeTypeFilters(mimeTypes);
	fileDialog.selectMimeTypeFilter( "image/" + format);
	fileDialog.setDefaultSuffix(format);

	if(fileDialog.exec() != QDialog::Accepted)
	{
		return;
	}

	const QString fileName = fileDialog.selectedFiles().first();
	if(!m_originalPixmap.save(fileName))
	{
		QMessageBox::warning(this , tr("Save Error") ,  tr("The image could not be saved to \"%1\".") .arg(QDir::toNativeSeparators(fileName)));
	}
}

void ScreenShot::shootScreen()
{
	QScreen * pScreen =  QGuiApplication::primaryScreen();
	if(const  QWindow* pWindow = windowHandle())
	{
		pScreen =  pWindow->screen();
	}

	if(nullptr==pScreen)
	{
		return;
	}

	if(m_pDelaySpinBox->value() != 0)
	{
		QApplication::beep();
	}

	m_originalPixmap = pScreen->grabWindow(0);
	updateScreenshotLabel();

	m_pNewScreenShotButton->setDisabled(false);

	if(m_pHideThisWindowCheckBox->isChecked())
	{
		show();
	}
}

void ScreenShot::updateCheckBox()
{
	if(m_pDelaySpinBox->value() == 0)
	{
		m_pHideThisWindowCheckBox->setDisabled(true);
		m_pHideThisWindowCheckBox->setChecked(false);
	}else{
		m_pHideThisWindowCheckBox->setDisabled(false);
	}
}

void ScreenShot::updateScreenshotLabel()
{
	m_pScreenshotLabel->setPixmap( m_originalPixmap.scaled(m_pScreenshotLabel->size() , Qt::KeepAspectRatio , Qt::SmoothTransformation));
}

void ScreenShot::init()
{
	m_pScreenshotLabel = new QLabel(this) ;
	m_pScreenshotLabel->setSizePolicy(QSizePolicy::Expanding  , QSizePolicy::Expanding);
	m_pScreenshotLabel->setAlignment(Qt::AlignCenter);

	const QRect screenGeometry = QApplication::desktop()->screenGeometry(this);
	m_pScreenshotLabel->setMinimumSize(screenGeometry.width()/8  ,  screenGeometry.height()/8);

	QVBoxLayout * mainLayout = new QVBoxLayout(this);
	mainLayout->addWidget(m_pScreenshotLabel);

	QGroupBox *optionsGroupBox = new QGroupBox( tr("Options") ,  this );
	m_pDelaySpinBox = new QSpinBox(optionsGroupBox);
	m_pDelaySpinBox->setSuffix(tr(" s "));
	m_pDelaySpinBox->setMaximum(60);

	connect(m_pDelaySpinBox  ,  QOverload<int>::of(&QSpinBox::valueChanged)  , this  ,  &ScreenShot::updateCheckBox);

	m_pHideThisWindowCheckBox = new QCheckBox(tr("Hide This Window") , optionsGroupBox );

	QGridLayout * optionsGroupboxLayout  = new QGridLayout(optionsGroupBox);
	optionsGroupboxLayout->addWidget(new QLabel(tr("Screenshot Delay:") ,this) , 0 , 0);
	optionsGroupboxLayout->addWidget(m_pDelaySpinBox , 0 , 1);
	optionsGroupboxLayout->addWidget(m_pHideThisWindowCheckBox , 1,0,1,2);

	mainLayout->addWidget(optionsGroupBox);

	QHBoxLayout *buttonslayout  = new QHBoxLayout;
	m_pNewScreenShotButton = new QPushButton(tr("New Screenshot"),this);
	connect(m_pNewScreenShotButton , &QPushButton::clicked , this  , &ScreenShot::newScreenshot);
	buttonslayout->addWidget(m_pNewScreenShotButton);

	QPushButton *saveScreenshotButton  = new QPushButton(tr("Save Screenshot"),this);
	connect(saveScreenshotButton , &QPushButton::clicked , this , &ScreenShot::saveScreenshot);
	buttonslayout->addWidget(saveScreenshotButton);

	QPushButton *quitScreenshotButton  = new QPushButton(tr("Quit") , this);
	quitScreenshotButton->setShortcut(Qt::CTRL + Qt::Key_Q);
	connect(quitScreenshotButton  , &QPushButton::clicked , this , &QWidget::close);
	buttonslayout->addWidget(quitScreenshotButton);
	buttonslayout->addStretch();

	mainLayout->addLayout(buttonslayout);
}

void ScreenShot::uninit()
{
	delete_ptr_if(m_pDelaySpinBox);
	delete_ptr_if(m_pHideThisWindowCheckBox);
	delete_ptr_if(m_pNewScreenShotButton);
	delete_ptr_if(m_pScreenshotLabel);
}
